﻿/*
 Lincense: https://discio.codeplex.com/license
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization; 


namespace Discio
{
    public static class Extensions
    {
   

        public static string SerializeToString(this IDiscio obj)
        {
            XmlSerializer serializer = new XmlSerializer(obj.GetType());

            using (StringWriter writer = new StringWriter())
            {
                serializer.Serialize(writer, obj);
                return writer.ToString();
            }
        }

        public static XmlElement SerializeToXmlElement(this object obj)
        {
            XmlDocument doc = new XmlDocument();

            using (XmlWriter writer = doc.CreateNavigator().AppendChild())
            {
                new XmlSerializer(obj.GetType()).Serialize(writer, obj);
            }

            return doc.DocumentElement;
        }

        public static T DeserializeFromXmlElement<T>(this XmlElement element)
        {
            var serializer = new XmlSerializer(typeof(T));
            T e = (T)serializer.Deserialize(new XmlNodeReader(element));

            return e.DecryptHelper<T>();
        }

        public static XElement ToXElement(this XmlElement element)
        {
            return XElement.Parse(element.OuterXml);
        }

        public static XmlElement ToXmlElement(this XElement element)
        {
            var doc = new XmlDocument();
            doc.LoadXml(element.ToString());
            return doc.DocumentElement;
        }

        /// <summary>
        /// Insert an IDiscioTable object to a set
        /// </summary> 
        /// <param name="setName">setName</param>
        public static void InsertTo(this IDiscio o, string setName)
        {
            var man = new DiscioManager(setName);
            man.Insert(o);
            man.Commit();
        }

        /// <summary>
        /// Insert a list of IDiscioTable objects to a set
        /// </summary> 
        /// <param name="setName">setName</param>
        public static void InsertTo(this List<IDiscio> l, string setName)
        {
            var man = new DiscioManager(setName);
            foreach (var o in l)
            {
                man.Insert(o);
            }
            man.Commit();
        }

         /// <summary>
        /// Encrypt a string using the local AES encryption class
        /// </summary>
        /// <param name="text">Text</param>
        /// <returns>Encrypted text</returns>
        public static string AESEncrypt(this string text)
        {
            AES enc = new AES();
            
            return enc.EncryptToString(text);
        }

        /// <summary>
        /// Decrypt a string previously encrypted by the local AES encryption class
        /// </summary>
        /// <param name="text">Encrypted text</param>
        /// <returns>Decrypted text</returns>
        public static string AESDecrypt(this string text)
        {
            AES enc = new AES();

            return enc.DecryptString(text);
        }

        public static T DecryptHelper<T>(this T item)
        {
            foreach (var p in item.GetType().GetProperties())
            {
                EncryptProperty[] m = (EncryptProperty[])p.GetCustomAttributes(typeof(EncryptProperty), false);
                if (m.Length > 0)
                {
                    if (p.PropertyType.Name.ToLower() == "string" && m[0].Behavior == true)
                    {
                        string text = item.GetType().GetProperty(p.Name).GetValue(item, null).ToString();
                        string decrypt = "";
                        try
                        {
                            decrypt = text.AESDecrypt();
                            text = decrypt;
                        }
                        catch (Exception ex)
                        {
                        }
                        item.GetType().GetProperty(p.Name).SetValue(item, text, null);
                    }
                }
            }

            return item;
        }

  

        public static List<IDiscio> EncryptHelper(this List<IDiscio> items)
        {
            return items.Select(m => m.EncryptHelper()).ToList();
        }

        public static IDiscio EncryptHelper(this IDiscio item)
        {
            foreach (var p in item.GetType().GetProperties())
            {
                EncryptProperty[] m = (EncryptProperty[])p.GetCustomAttributes(typeof(EncryptProperty), false);
                if (m.Length > 0)
                {
                    if (p.PropertyType.Name.ToLower() == "string")
                    {
                        if (m[0].Behavior == true)
                        {
                            string text = item.GetType().GetProperty(p.Name).GetValue(item, null).ToString(); 
                            item.GetType().GetProperty(p.Name).SetValue(item, text.AESEncrypt(), null);
                        }
                    }
                }
            }

            return item;
        }

    }
}
